package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author atguigu-mqx
 * @Description TODO
 * @Date 2023/8/30 15:30
 * @Version 1.0
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;



    /*
        添加购物车业务逻辑！
        判断当前购物车中是否有该商品：
            true:
                商品数量相加
                商品的skuNum 最大200 skuNum>200 200
                每次添加时都是默认选中
                更新一下商品的修改时间
                展示商品最新价格
            false:
                直接添加商品
                hset key field value;
         */
    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {
        //  组成购物车的key = user:userId:cart
        String cartKey = getCartKey(userId);
        //  判断当前购物车中是否有该商品 hget key field;
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (null != cartInfoExist){
            //  有这个商品！
            Integer number = cartInfoExist.getSkuNum()+skuNum>200?200:cartInfoExist.getSkuNum()+skuNum;
            cartInfoExist.setSkuNum(number);
            //  设置为选中状态
            cartInfoExist.setIsChecked(1);
            //            if (cartInfoExist.getIsChecked().intValue()==0) {
            //                cartInfoExist.setIsChecked(1);
            //            }
            cartInfoExist.setUpdateTime(new Date());
            cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            //  需要将这个数据保存到缓存 hset key field value;
            //  this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        } else {
            //    第一次添加该商品.
            cartInfoExist = new CartInfo();
            //  通过skuId 获取商品基本信息
            SkuInfo skuInfo = this.productFeignClient.getSkuInfo(skuId);
            //  赋值信息
            cartInfoExist.setSkuId(skuId);
            //  防止用户修改url地址中的skuNum
            cartInfoExist.setSkuNum(skuNum>200?200:skuNum);
            cartInfoExist.setUserId(userId);
            cartInfoExist.setCartPrice(skuInfo.getPrice());
            cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());
        }
        //  需要将这个数据保存到缓存 hset key field value;
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        //  写过期的话：1年 ---> 获取每个用户的购买力度！ userId ---> totalAmount 总金额
        //  1个月：70w 2年 淘宝 40w if()else if() else if(){}else{1个月} --- 工厂模式

    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  获取到购物车key
        String cartKey = this.getCartKey(userId);
        //  根据key要获取到所有的商品，再判断是否选中.
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  需要获取到选中的商品
        List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked().intValue()==1).collect(Collectors.toList());
        //  返回选中商品
        return cartInfoCheckedList;
    }

    @Override
    public void clearCart(String userId) {
        //  del key
        this.redisTemplate.delete(this.getCartKey(userId));
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //  hdel key field;
        this.redisTemplate.opsForHash().delete(this.getCartKey(userId),skuId.toString());
    }

    @Override
    public void allCheckCart(Integer isChecked, String userId) {
        //  获取到修改对象 hget key field;
        String cartKey = this.getCartKey(userId);
        //  获取购物车数据
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  声明一个map 集合
        //        HashMap<String, CartInfo> hashMap = new HashMap<>();
        //        //  判断
        //        if (!CollectionUtils.isEmpty(cartInfoList)){
        //            //  遍历。
        //            for (CartInfo cartInfo : cartInfoList) {
        //                cartInfo.setIsChecked(isChecked);
        //                //  this.redisTemplate.opsForHash().put(cartKey,cartInfo.getSkuId().toString(),cartInfo);
        //                hashMap.put(cartInfo.getSkuId().toString(),cartInfo);
        //            }
        //        }
        //  接下来要将的东西，能听懂，就听懂！
        //  hmset key map;
        //  this.redisTemplate.opsForHash().putAll(cartKey,hashMap);
        Map<String, CartInfo> map = cartInfoList.stream().map(cartInfo -> {
            cartInfo.setIsChecked(isChecked);
            return cartInfo;
        }).collect(Collectors.toMap(cartInfo -> cartInfo.getSkuId().toString(), cartInfo -> cartInfo));
        //  将数据放入缓存.
        this.redisTemplate.opsForHash().putAll(cartKey,map);
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked, String userId) {
        //  获取到修改对象 hget key field;
        String cartKey = this.getCartKey(userId);
        //  获取数据
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey,skuId.toString());
        if (null != cartInfo){
            //  赋值选中状态
            cartInfo.setIsChecked(isChecked);
//            cartInfo.setUpdateTime(new Date());
        }
        //  写回缓存 hset key field value;
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
    }

    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        /*
        分析合并购物车过程：
            case 1: userId

            case 2: userTempId

            case 3: userId + userTempId

            1.  userId + userTempId 必须同时存在！
                    userId-存在，并且通过临时userTempId 查询数据，临时购物车集合中必须也数据，此时才能发生合并购物车！

            登录：
                26  1 1
                27  1 0
                28  1 1

            未登录：
                26  1 1
                27  1 0
                28  1 0
                29  1 1

             合并： 合并完成之后，从哪里获取的数据！ 登录的购物车了;
                26  2
                27  2
                28  2
                29  1

            未登录： 删除了，就不存在了！
         */

        //  声明一个集合来存储临时购物车
        List<CartInfo> cartInfoNoLoginList = new ArrayList<>();
        //  判断
        if (!StringUtils.isEmpty(userTempId)){
            //  获取临时购物车key
            String cartKey = this.getCartKey(userTempId);
            //  获取购物车集合
            cartInfoNoLoginList = this.redisTemplate.opsForHash().values(cartKey);
        }
        //  如果要是没有登录，则返回并排序.
        if (StringUtils.isEmpty(userId)){
            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                //  安装修改时间进行排序。
                cartInfoNoLoginList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(), Calendar.SECOND));
            }
             //  返回集合
            return cartInfoNoLoginList;
        }

        //  至少有userId
        //  声明一个集合来存储登录购物车
        List<CartInfo> cartInfoLoginList = new ArrayList<>();
        //  获取登录购物车key
        String cartKey = this.getCartKey(userId);
        //  boundHashOps() 也可以操作 opsForHash()
        //  BoundHashOperations<H, HK, HV> hset key field value
        BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
        //  cartInfoLoginList = this.redisTemplate.opsForHash().values(cartKey);
        //  有可能会发生合并.
        if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
            //  一定要合并了. 合并购物车的条件 skuId 必须要相同.
            //  循环遍历未登录购物车集合
            for (CartInfo cartInfoNoLogin : cartInfoNoLoginList) {
                //  判断登录对象中是否包含未登录的skuId 26 27 28
                if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())){
                    //  说明skuId 相同 未登录添加到登录中
                    CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                    Integer number = cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum()>200?200:cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum();
                    cartInfoLogin.setSkuNum(number);
                    //  设置一下修改时间
                    cartInfoLogin.setUpdateTime(new Date());
                    //  选中问题：合并选中的，还是选中与不选中都 合并呢 ?
                    if (cartInfoNoLogin.getIsChecked().intValue()==1){
                        cartInfoLogin.setIsChecked(1);
                    }
                    //  if (cartInfoLogin.getCartPrice().compareTo(cartInfoLogin.getSkuPrice())!=0) {
                    //      //  计算价格：变化金额
                    //      cartInfoLogin.getCartPrice().subtract(cartInfoLogin.getSkuPrice()).abs();
                    //  }
                    //  价格暂时以数据库为准.
                    //  写回缓存.
                    boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoLogin);
                } else {
                    //  不相同 29
                    //  相当于新增。
                    //  if (cartInfoNoLogin.getIsChecked().intValue()==1){
                    //      cartInfoNoLogin.setUserId(userId);
                    //      cartInfoNoLogin.setCreateTime(new Date());
                    //      cartInfoNoLogin.setUpdateTime(new Date());
                    //      //  选中不选中?
                    //      boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    //  }
                    cartInfoNoLogin.setUserId(userId);
                    //  限制购买数量。
                    cartInfoNoLogin.setSkuNum(cartInfoNoLogin.getSkuNum()>200?200:cartInfoNoLogin.getSkuNum());
                    cartInfoNoLogin.setCreateTime(new Date());
                    cartInfoNoLogin.setUpdateTime(new Date());
                    //  选中不选中?
                    boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                }
            }
            //  删除未登录购物车集合数据：
            this.redisTemplate.delete(this.getCartKey(userTempId));
        }
        //  表示既有合并之后，也有没有合并只有登录的业务！
        cartInfoLoginList = boundHashOperations.values();
        if (CollectionUtils.isEmpty(cartInfoLoginList)){
            //  返回空对象即可
            return new ArrayList<CartInfo>();
        }
        //  查看购物车的时候，需要按照更新时间进行排序.
        cartInfoLoginList.sort((cart1,cart2)-> DateUtil.truncatedCompareTo(cart2.getUpdateTime(),cart1.getUpdateTime(), Calendar.SECOND));
        //  返回登录数据
        return cartInfoLoginList;
    }
    /**
     * 获取购物车的key
     * @param userId
     * @return
     */
    public String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX+ userId +RedisConst.USER_CART_KEY_SUFFIX;
    }

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 4, 3, 7, 5);
        //        list.sort((a,b)-> b-a);
        //        System.out.println(list);

        List<Integer> integerList = list.stream().peek(a -> a.byteValue()).collect(Collectors.toList());
//        System.out.println(list);
        System.out.println(integerList);
    }
}
